package com.ynet.middleground.user.model;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

import org.apache.commons.lang3.StringUtils;
import org.dozer.Mapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ynet.cache.redis.IfpRedisson;
import com.ynet.core.common.BaseReqObjPager;
import com.ynet.core.common.PagerInfo;
import com.ynet.core.exception.BusinessException;
import com.ynet.core.log.IfpLogger;
import com.ynet.middleground.user.bean.*;
import com.ynet.middleground.user.dao.ChannelConfigMapper;
import com.ynet.middleground.user.dao.TableResourcesMapper;
import com.ynet.middleground.user.dto.ChannelDTO;
import com.ynet.middleground.user.dto.ResourceDto;
import com.ynet.middleground.user.dto.TableResourceDto;
import com.ynet.middleground.user.entity.*;
import com.ynet.middleground.user.utils.BeanUtil;
import com.ynet.middleground.user.utils.CommUtils;

/**
 * <p>
 * 渠道信息表 服务实现类
 * </p>
 *
 * @author yangbh
 * @since 2019-10-16
 */
@Component
public class ChannelConfigModel extends ServiceImpl<ChannelConfigMapper, ChannelConfig> {

    @Autowired
    private IfpRedisson redisson;

    @Autowired
    private Mapper mapper;

    @Autowired
    private ResourceConfigModel resourceConfigModel;

    @Autowired
    private ChannelResourceConfigModel channelResourceConfigModel;

    @Autowired
    private TableResourcesMapper tableResourcesMapper;

    @Autowired
    private ChannelResourceModel channelResourceModel;

    /**
     * 根据渠道id查询所有资源
     *
     * @param channelId
     * @return
     */
    public List<ResourceDto> resourceList(long channelId) {

        QueryWrapper<ChannelResourceConfig> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("channel_id", channelId);

        // 查询所有配置信息
        List<ChannelResourceConfig> channelResourceConfigs = channelResourceConfigModel.list(queryWrapper);

        if (channelResourceConfigs.isEmpty()) {
            return new ArrayList<>();
        }

        // 获取资源ids
        List<Integer> resourceIds =
            channelResourceConfigs.stream().map(x -> x.getChannelId()).collect(Collectors.toList());

        // 查询所有资源列表
        Collection<ResourceConfig> resourceConfigs = resourceConfigModel.listByIds(resourceIds);

        // 对象转换
        List<ResourceDto> result =
            resourceConfigs.stream().map(x -> mapper.map(x, ResourceDto.class)).collect(Collectors.toList());

        return result;

    }

    public void doSyncChannelResource() {
        List<ChannelConfig> channelConfigs = this.list();

        channelConfigs.forEach(x -> {
            IfpLogger.info("channel", "开始查询渠道id:{}", x.getId());

            List<String> apis = this.baseMapper.searchResourcesByChannel(x.getId());
            if (null != apis && !apis.isEmpty()) {
                Map<Integer, List<String>> redisMap = new HashMap<>();
                redisMap.put(x.getId(), apis);
                IfpLogger.info("channel", "开始查询渠道资源列表id:{},Resource:{}", x.getId(), apis.size());
                // redisson.set(DubboChannelFilter.IFP_CHANNEL_CACHE, redisMap);
            }
            IfpLogger.info("channel", "开始查询渠道资源列表id:{}, api空", x.getId());

        });
    }

    /**
     * 校验渠道信息是否重复
     *
     * @param channelCode 渠道编码
     * @param channelName 渠道名称
     * @author liulx
     * @date 2020-07-01
     */
    public void checkRepeatChannel(String channelCode, String channelName) {
        LambdaQueryWrapper<ChannelConfig> channelConfigWrapper = new LambdaQueryWrapper<>();
        channelConfigWrapper.eq(ChannelConfig::getIsDeleted, "0");
        if (StringUtils.isNotBlank(channelCode)) {
            channelConfigWrapper.eq(ChannelConfig::getChannelCode, channelCode);
            int count = this.count(channelConfigWrapper);
            if (count > 0) {
                throw new BusinessException("渠道代码重复，请重新输入。", "ECUC0100");
            }
        }
        if (StringUtils.isNotBlank(channelName)) {
            channelConfigWrapper = new LambdaQueryWrapper<>();
            channelConfigWrapper.eq(ChannelConfig::getIsDeleted, "0");
            channelConfigWrapper.eq(ChannelConfig::getChannelName, channelName);
            int count = this.count(channelConfigWrapper);
            if (count > 0) {
                throw new BusinessException("渠道名称重复，请重新输入。", "ECUC0101");
            }
        }
    }

    /**
     * 保存渠道
     *
     * @param req 新增渠道请求对象
     * @return 保存成功后的渠道 id
     */
    public Integer saveChannel(AddChannelReq req) {
        // 校验渠道号是否重复
        checkRepeatChannel(req.getChannelCode(), req.getChannelName());
        ChannelConfig channelConfig = mapper.map(req, ChannelConfig.class);
        channelConfig.setGmtCreate(LocalDateTime.now());
        channelConfig.setCreateBy(req.getOperationUserId());
        channelConfig.setGmtModified(LocalDateTime.now());
        channelConfig.setModifiedBy(req.getOperationUserId());
        channelConfig.setStatus(true);
        this.save(channelConfig);
        return channelConfig.getId();
    }

    /**
     * 根据渠道 id 查询渠道信息
     *
     * @param req 查询基础对象
     * @return 渠道信息传输对象
     */
    public ChannelDTO getDetailById(QueryBaseReq req) {
        ChannelConfig channel = this.getById(req.getId());
        if (channel == null || channel.getIsDeleted()) {
            throw new BusinessException("该渠道信息不存在", "ECUC0102");
        }
        return mapper.map(channel, ChannelDTO.class);
    }

    /**
     * 根据渠道 id 查询渠道信息
     * 
     * @param channelCode 渠道编码
     * @return 渠道信息传输对象
     */
    public ChannelDTO getDetailByCode(String channelCode) {
        LambdaQueryWrapper<ChannelConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChannelConfig::getIsDeleted, "0");
        queryWrapper.eq(ChannelConfig::getChannelCode, channelCode);
        ChannelConfig channel = this.getOne(queryWrapper);
        if (channel == null || channel.getIsDeleted()) {
            throw new BusinessException("[" + channelCode + "] 该渠道信息不存在", "ECUC0102");
        }
        return mapper.map(channel, ChannelDTO.class);
    }

    /**
     * 查询所有渠道
     *
     * @return 所有渠道列表
     */
    public List<ChannelDTO> listAll() {
        LambdaQueryWrapper<ChannelConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChannelConfig::getIsDeleted, "0");
        List<ChannelConfig> list = this.list(queryWrapper);
        return BeanUtil.mapList(mapper, list, ChannelDTO.class);
    }
    
    /**
     * 查询所有渠道
     *
     * @return 所有渠道列表
     */
    public List<ChannelDTO> listAlls(searchAllChannelsReq req) {
        LambdaQueryWrapper<ChannelConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChannelConfig::getIsDeleted, "0");
        if(StringUtils.isNotEmpty(req.getQueryChannel())) {
            queryWrapper.eq(ChannelConfig::getChannelCode, req.getQueryChannel());
        }
        List<ChannelConfig> list = this.list(queryWrapper);
        return BeanUtil.mapList(mapper, list, ChannelDTO.class);
    }

    /**
     * 分页查询渠道
     *
     * @param req 基础参数分页
     * @return 渠道列表
     */
    public List<ChannelDTO> listPage(BaseReqObjPager req) {
        PagerInfo pagerInfo = req.getPagerInfo();
        LambdaQueryWrapper<ChannelConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChannelConfig::getIsDeleted, "0");
        Page<ChannelConfig> page = new Page<>(pagerInfo.getPageNum(), pagerInfo.getPageSize());
        IPage<ChannelConfig> iPage = this.page(page, queryWrapper);
        List<ChannelConfig> list = iPage.getRecords();
        pagerInfo.setTotal(iPage.getTotal());
        return BeanUtil.mapList(mapper, list, ChannelDTO.class);
    }

    /**
     * 更新渠道信息
     *
     * @param req 修改渠道信息请求对象
     */
    @Transactional(rollbackFor = Exception.class)
    public void modify(UpdateChannelReq req) {
        ChannelConfig channel = this.getById(req.getId());
        if (channel == null || channel.getIsDeleted()) {
            throw new BusinessException("该渠道信息不存在", "ECUC0102");
        }
        LambdaQueryWrapper<ChannelConfig> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChannelConfig::getIsDeleted, "0");
        queryWrapper.eq(ChannelConfig::getChannelName, req.getChannelName());
        List<ChannelConfig> channelConfigs = this.list(queryWrapper);
        if (channelConfigs != null) {
            if (channelConfigs.size() > 1) {
                throw new BusinessException("渠道名称重复，请重新输入。", "ECUC0101");
            }
            if (channelConfigs.size() == 1) {
                ChannelConfig existChannel = channelConfigs.get(0);
                if (!existChannel.getId().equals(req.getId())) {
                    throw new BusinessException("渠道名称重复，请重新输入。", "ECUC0101");
                }
            }
        }
        mapper.map(req, channel);
        channel.setGmtModified(LocalDateTime.now());
        channel.setModifiedBy(req.getOperationUserId());
        this.updateById(channel);
    }

    /**
     * 添加资源信息
     * 
     * @param addTableResource
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean addTableResource(AddTableResourceReq addTableResource) {
        checkRepeatResource(addTableResource.getTableCode(), addTableResource.getTableName());
        TableResources map = mapper.map(addTableResource, TableResources.class);
        map.setCreateBy(addTableResource.getOperationUserId());
        map.setModifiedBy(addTableResource.getOperationUserId());
        map.setStatus(0);
        map.setGmtCreate(LocalDateTime.now());
        map.setGmtModified(LocalDateTime.now());
        return tableResourcesMapper.insert(map) > 0;
    }

    /**
     * 根据id更新资源信息
     * 
     * @param req 修改资源信息参数
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateTableResource(UpdateTableResourceReq req) {
        TableResources map = mapper.map(req, TableResources.class);
        if (map == null) {
            throw new BusinessException("该资源信息不存在", "ECUC0302");
        }
        LambdaQueryWrapper<TableResources> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TableResources::getStatus, 0);
        queryWrapper.eq(TableResources::getTableName, req.getTableName());
        List<TableResources> resources = tableResourcesMapper.selectList(queryWrapper);
        if (resources != null) {
            if (resources.size() > 1) {
                throw new BusinessException("资源名称重复，请重新输入。", "ECUC0301");
            }
            if (resources.size() == 1) {
                TableResources exist = resources.get(0);
                if (!exist.getId().equals(req.getId())) {
                    throw new BusinessException("资源名称重复，请重新输入。", "ECUC0301");
                }
            }
        }
        map.setGmtModified(LocalDateTime.now());
        map.setModifiedBy(req.getOperationUserId());
        return tableResourcesMapper.updateById(map) > 0;
    }

    /**
     * 根据id删除资源信息
     * 
     * @param req 查询基础对象
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteTableResource(QueryBaseReq req) {
        TableResources resources = tableResourcesMapper.selectById(req.getId());
        if (resources == null) {
            throw new BusinessException("该资源信息不存在", "ECUC0302");
        }
        String code = resources.getTableCode();
        boolean delete = tableResourcesMapper.deleteById(req.getId()) > 0;
        LambdaQueryWrapper<ChannelResources> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ChannelResources::getIsDeleted, "0");
        queryWrapper.eq(ChannelResources::getTableCode, code);
        channelResourceModel.remove(queryWrapper);
        if (delete) {
            redisson.getBucket(CommUtils.getRedisKey(code)).delete();
        }
        return delete;
    }

    /**
     * 查询所有正常状态的资源配置信息
     * 
     * @return
     */
    public List<TableResourceDto> queryAllTableResource() {
        List<TableResourceDto> tableDtos = new ArrayList<>();
        LambdaQueryWrapper<TableResources> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TableResources::getStatus, 0);
        List<TableResources> tableResources = tableResourcesMapper.selectList(queryWrapper);
        tableResources.forEach(x -> tableDtos.add(mapper.map(x, TableResourceDto.class)));
        return tableDtos;
    }

    /**
     * 查询资源详情
     * 
     * @param req 查询基础对象
     * @return 资源信息对象
     */
    public TableResourceDto getResourceDetail(QueryBaseReq req) {
        TableResources resources = tableResourcesMapper.selectById(req.getId());
        if (resources == null) {
            throw new BusinessException("该资源信息不存在", "ECUC0302");
        }
        return mapper.map(resources, TableResourceDto.class);
    }

    /**
     * 分页查询正常状态的资源配置信息
     * 
     * @param req 基础参数分页
     * @return 资源配置列表
     * @autor liulx
     * @date 2020-07-06 14:56:36
     */
    public List<TableResourceDto> queryTableResourceByPage(BaseReqObjPager req) {
        PagerInfo pagerInfo = req.getPagerInfo();
        LambdaQueryWrapper<TableResources> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TableResources::getStatus, 0);
        Page<TableResources> page = new Page<>(pagerInfo.getPageNum(), pagerInfo.getPageSize());
        IPage<TableResources> iPage = tableResourcesMapper.selectPage(page, queryWrapper);
        List<TableResources> list = iPage.getRecords();
        pagerInfo.setTotal(iPage.getTotal());
        return BeanUtil.mapList(mapper, list, TableResourceDto.class);
    }

    /**
     * 校验资源信息是否重复
     *
     * @param tableCode 资源编码
     * @param tableName 资源名称
     * @author liulx
     */
    public void checkRepeatResource(String tableCode, String tableName) {
        LambdaQueryWrapper<TableResources> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(TableResources::getStatus, 0);
        if (StringUtils.isNotBlank(tableCode)) {
            queryWrapper.eq(TableResources::getTableCode, tableCode);
            int count = tableResourcesMapper.selectCount(queryWrapper);
            if (count > 0) {
                throw new BusinessException("资源代码重复，请重新输入。", "ECUC0300");
            }
        }
        if (StringUtils.isNotBlank(tableName)) {
            queryWrapper = new LambdaQueryWrapper<>();
            queryWrapper.eq(TableResources::getStatus, 0);
            queryWrapper.eq(TableResources::getTableName, tableName);
            int count = tableResourcesMapper.selectCount(queryWrapper);
            if (count > 0) {
                throw new BusinessException("资源名称重复，请重新输入。", "ECUC0301");
            }
        }
    }

}
